import type {
  LogEvent,
  LogGetFilesRequest,
  LogGetFilesResponse,
  LogSubscribeRequest,
} from '@shared/types/ipc'
import type { LogSearchOptions } from '../logger/index'
import { readdir, stat } from 'node:fs/promises'
import { join } from 'node:path'
// 日志管理 IPC 处理器
import { app, BrowserWindow, ipcMain } from 'electron'
import { getLogsPath } from '../config/index'
import { getLogger, getLogMetrics, getLogStats, resetLogMetrics, searchLogs } from '../logger/index'

// 日志订阅管理
const logSubscriptions = new Map<number, {
  level?: string
  source?: string
}>()

/**
 * 设置日志处理器
 *
 * @description 设置日志处理器，包括订阅、取消订阅、获取日志文件列表、读取日志文件内容、获取日志指标、重置日志指标、搜索日志
 */
export function setupLogHandlers(): void {
  const logger = getLogger()

  // 日志：订阅
  ipcMain.handle('log:subscribe', async (event, request: LogSubscribeRequest) => {
    try {
      const webContentsId = event.sender.id

      // 保存订阅信息
      logSubscriptions.set(webContentsId, {
        level: request.level,
        source: request.source,
      })

      logger.info(`✅ 日志订阅已建立: webContents-${webContentsId}`, request)

      // 返回取消订阅的函数
      return {
        success: true,
        message: '日志订阅已建立',
      }
    }
    catch (error: any) {
      logger.error('建立日志订阅失败:', error)
      return {
        success: false,
        error: error?.message || String(error),
      }
    }
  })

  // 日志：取消订阅
  ipcMain.handle('log:unsubscribe', async (event) => {
    try {
      const webContentsId = event.sender.id
      logSubscriptions.delete(webContentsId)

      logger.info(`✅ 日志订阅已取消: webContents-${webContentsId}`)

      return {
        success: true,
        message: '日志订阅已取消',
      }
    }
    catch (error: any) {
      logger.error('取消日志订阅失败:', error)
      return {
        success: false,
        error: error?.message || String(error),
      }
    }
  })

  // 日志：获取日志文件列表
  ipcMain.handle('log:get-files', async (_event, request: LogGetFilesRequest): Promise<LogGetFilesResponse> => {
    try {
      const logsPath = getLogsPath()
      const files = await readdir(logsPath)

      const logFiles: Array<{
        file_path: string
        date: string
        level: string
        size: number
        last_modified: number
      }> = []

      for (const file of files) {
        if (file.endsWith('.log')) {
          const filePath = join(logsPath, file)
          const stats = await stat(filePath)

          // 解析文件名获取日期和级别
          const match = file.match(/^(app|error|exceptions|rejections)-(\d{4}-\d{2}-\d{2})\.log$/)
          const level = match ? match[1] : 'unknown'
          const date = match ? match[2] : ''

          // 日期范围过滤
          if (request.date_range) {
            if (date < request.date_range.start || date > request.date_range.end) {
              continue
            }
          }

          logFiles.push({
            file_path: filePath,
            date,
            level,
            size: stats.size,
            last_modified: Math.floor(stats.mtime.getTime() / 1000),
          })
        }
      }

      // 按日期降序排序
      logFiles.sort((a, b) => b.date.localeCompare(a.date))

      return {
        success: true,
        files: logFiles,
      }
    }
    catch (error: any) {
      logger.error('获取日志文件列表失败:', error)
      return {
        success: false,
        files: [],
        error: error?.message || String(error),
      }
    }
  })

  // 日志：读取日志文件内容
  ipcMain.handle('log:read-file', async (_event, filePath: string, options?: { lines?: number, offset?: number }) => {
    try {
      const { readFile } = await import('node:fs/promises')
      const content = await readFile(filePath, 'utf-8')

      let lines = content.split('\n')

      if (options?.offset) {
        lines = lines.slice(options.offset)
      }

      if (options?.lines) {
        lines = lines.slice(0, options.lines)
      }

      return {
        success: true,
        content: lines.join('\n'),
        total_lines: content.split('\n').length,
      }
    }
    catch (error: any) {
      logger.error('读取日志文件失败:', error)
      return {
        success: false,
        content: '',
        error: error?.message || String(error),
      }
    }
  })

  // 日志：获取日志指标
  ipcMain.handle('log:get-metrics', async () => {
    try {
      return {
        success: true,
        metrics: getLogMetrics(),
        stats: getLogStats(),
      }
    }
    catch (error: any) {
      logger.error('获取日志指标失败:', error)
      return {
        success: false,
        error: error?.message || String(error),
      }
    }
  })

  // 日志：重置指标
  ipcMain.handle('log:reset-metrics', async () => {
    try {
      resetLogMetrics()
      logger.info('📊 日志指标已重置')
      return {
        success: true,
        message: '日志指标已重置',
      }
    }
    catch (error: any) {
      logger.error('重置日志指标失败:', error)
      return {
        success: false,
        error: error?.message || String(error),
      }
    }
  })

  // 日志：搜索日志
  ipcMain.handle('log:search', async (_event, options: LogSearchOptions) => {
    try {
      const result = await searchLogs(options)
      return {
        success: true,
        ...result,
      }
    }
    catch (error: any) {
      logger.error('搜索日志失败:', error)
      return {
        success: false,
        results: [],
        total: 0,
        hasMore: false,
        error: error?.message || String(error),
      }
    }
  })

  // 注册事件监听器（需要在应用启动时调用）
  app.on('web-contents-created', (_event, webContents) => {
    webContents.on('destroyed', () => {
      logSubscriptions.delete(webContents.id)
    })
  })
}

// 广播日志事件到所有订阅者
export function broadcastLogEvent(logEvent: LogEvent): void {
  const allWindows = BrowserWindow.getAllWindows()

  for (const window of allWindows) {
    const webContentsId = window.webContents.id
    const subscription = logSubscriptions.get(webContentsId)

    if (!subscription)
      continue

    // 检查级别过滤
    if (subscription.level && logEvent.level !== subscription.level) {
      continue
    }

    // 检查来源过滤
    if (subscription.source && logEvent.source !== subscription.source) {
      continue
    }

    // 发送日志事件
    try {
      window.webContents.send('log:event', logEvent)
    }
    catch (error) {
      console.error('发送日志事件失败:', error)
    }
  }
}

// 创建日志事件
export function createLogEvent(
  level: string,
  message: string,
  source: string = 'main',
  data?: any,
  traceId?: string,
): LogEvent {
  return {
    timestamp: Date.now(),
    level,
    source,
    message,
    data,
    trace_id: traceId,
  }
}
